package cn.buyclss.microapp.service.impl;

import cn.buyclss.microapp.config.jwt.JwtConfig;
import cn.buyclss.microapp.entity.domain.Customer;
import cn.buyclss.microapp.entity.domain.WxAccount;
import cn.buyclss.microapp.entity.domain.WxAccountExample;
import cn.buyclss.microapp.entity.dto.Code2SessionResponse;
import cn.buyclss.microapp.entity.support.RespCode;
import cn.buyclss.microapp.entity.support.RespResult;
import cn.buyclss.microapp.mapper.CustomerMapper;
import cn.buyclss.microapp.mapper.WxAccountMapper;
import cn.buyclss.microapp.service.WxAppletLoginService;
import cn.buyclss.microapp.util.HttpUtil;
import cn.buyclss.microapp.util.JSONUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: Cecurio
 * @create: 2019-03-08 19:50
 **/
@Service
public class WxAppletLoginServiceImpl implements WxAppletLoginService {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${wx.applet.appid}")
    private String appId;

    @Value("${wx.applet.appsecret}")
    private String appSecret;

    @Autowired
    private WxAccountMapper wxAccountMapper;

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private JwtConfig jwtConfig;

    /**
     * 微信的 code2session 接口 获取微信用户信息
     * 官方说明 : https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/code2Session.html
     */
    private String code2Session(String jsCode) {
        String code2SessionUrl = "https://api.weixin.qq.com/sns/jscode2session";
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("appid", appId);
        params.add("secret", appSecret);
        params.add("js_code", jsCode);
        params.add("grant_type", "authorization_code");
        URI code2Session = HttpUtil.getURIwithParams(code2SessionUrl, params);
        return restTemplate.exchange(code2Session,
            HttpMethod.GET,
            new HttpEntity<String>(new HttpHeaders()), String.class).getBody();
    }

    @Override
    public RespResult wxUserLogin(String code) throws AuthenticationException {
        //1 . code2session返回JSON数据
        String resultJson = code2Session(code);
        //2 . 解析数据
        Code2SessionResponse response = JSONUtil.jsonString2Object(resultJson, Code2SessionResponse.class);
        if (!response.getErrcode().equals("0")) {
            throw new AuthenticationException("code已被使用");
        } else {
            // 3. 先从本地数据库查找
            Customer customer = customerMapper.selectCustomerByOpenId(response.getOpenid());

            if (customer == null) {
                customer = new Customer();
                customer.setWechatOpenid(response.getOpenid());
                customer.setSessionKey(response.getSession_key());
                customer.setCreatedTime(new Date());
                customer.setUpdatedTime(new Date());
                customerMapper.insertSelective(customer);
            }

            //5 . JWT 返回自定义登陆态 Token
            String token = jwtConfig.createTokenByWxAccount(customer);
            RespResult res = new RespResult();
            res.setCode(RespCode.SUCCESS);
            res.setErrMsg("");
            Map<String, Object> map = new HashMap<>();
            map.put("token", token);
            res.setData(map);
            return res;
        }
    }
}
